package promotion

import (
	sqlc "bp/db/sqlc"
	"bp/internal/render"
	sharedConv "bp/internal/rpcserver/shared/conv"
	sharedVld "bp/internal/rpcserver/shared/vld"
	"bp/internal/service/entity/promotion"
	"bp/internal/service/param"
	"bp/internal/util"
	promotionGrpc "bp/rpc/gen/webapi/promotion"
	"context"
)

// VldCreatePromotionReq 验证新建促销活动请求
func (s *PromotionWebApiImp) VldCreatePromotionReq(ctx context.Context, q *sqlc.Queries, req *promotionGrpc.CreatePromotionReq) (
	ptr *promotion.CreatePromotionParam,
	itemCategoryConfPtrs param.ItemCategoryConfigurationPtrArray,
	itemConfPtrs param.ItemConfigurationPtrArray,
	err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	token := util.GetBilinToken(ctx)

	if !sharedVld.IsOwnerType(req.OwnerType) {
		err = render.InvalidArgumentValue("owner_type")
		return
	}
	if req.OwnerId < 0 {
		err = render.InvalidArgumentRange("owner_id")
		return
	}
	if req.OwnerType == string(sqlc.EmOwnerTypeStore) && req.OwnerId == 0 {
		err = render.ArgumentMismatch("owner_type", "owner_id")
		return
	}
	if util.IsEmpty(req.Name) {
		err = render.ArgumentEmpty("name")
		return
	}
	if !sharedVld.IsPromotionNature(req.Nature) {
		err = render.InvalidArgumentValue("nature")
		return
	}
	if !sharedVld.IsOfferCategory(req.OfferCategory) {
		err = render.InvalidArgumentValue("offer_category")
		return
	}
	if !sharedVld.IsOfferType(req.OfferType) {
		err = render.InvalidArgumentValue("offer_type")
		return
	}
	if !sharedVld.IsIssuer(req.Issuer) {
		err = render.InvalidArgumentValue("issuer")
		return
	}
	if req.NeedVerifyQualification {
		if !sharedVld.IsQualifyTypeArray(req.QualifyTypes, false) {
			err = render.InvalidArgumentValue("qualify_types")
			return
		}
	}
	if req.Price < 0 {
		err = render.InvalidArgumentRange("price")
		return
	}
	if req.Quota < 0 {
		err = render.InvalidArgumentRange("quota")
		return
	}
	if req.OffMaximum < 0 {
		err = render.InvalidArgumentRange("off_maximum")
		return
	}
	var offMaximum int32 = -1
	switch sqlc.EmOfferType(req.OfferType) {
	case sqlc.EmOfferTypeDiscount:
		if req.Price > 100 {
			err = render.InvalidArgumentRange("price[0,100]")
			return
		}
		if req.OffMaximum <= req.Quota {
			err = render.InvalidArgumentRange("off_maximum<=quota")
			return
		}
		if req.OffMaximum > 0 {
			offMaximum = req.OffMaximum
		}
	}
	if !util.IsEmpty(req.DateChooseType) && !sharedVld.IsChooseType(req.DateChooseType) {
		err = render.InvalidArgumentValue("date_choose_type")
		return
	}
	if !sharedVld.IsOfferUseSceneArray(req.UseScenes, false) {
		err = render.InvalidArgumentValue("use_scenes")
		return
	}
	if !sharedVld.IsScope(req.Scope) {
		err = render.InvalidArgumentValue("scope")
		return
	}
	if req.ParentId < 0 {
		err = render.InvalidArgumentRange("parent_id")
		return
	}
	if req.CopySource < 0 {
		err = render.InvalidArgumentRange("copy_source")
		return
	}

	ptr = &promotion.CreatePromotionParam{
		CreatePromotionParamsPtr: &sqlc.CreatePromotionParams{
			BrandID:                 token.BrandID,
			OwnerType:               req.OwnerType,
			OwnerID:                 req.OwnerId,
			Name:                    req.Name,
			Desc:                    sqlc.NSFromString(req.Desc),
			Tags:                    req.Tags,
			Nature:                  req.Nature,
			OfferCategory:           req.OfferCategory,
			OfferType:               req.OfferType,
			Issuer:                  req.Issuer,
			NeedVerifyQualification: req.NeedVerifyQualification,
			Price:                   req.Price,
			Quota:                   req.Quota,
			OffMaximum:              offMaximum,
			GradientRules:           sharedConv.ConvOffGradientRuleArrayPbToEntity(req.GradientRules),
			Begined:                 sqlc.PBTimestampToGoTime(req.Begined),
			Ended:                   sqlc.PBTimestampToGoTime(req.Ended),
			TimeRanges:              sharedConv.ConvTimeRangeArrayPbToEntity(req.TimeRanges),
			DateChooseType:          sqlc.NSFromString(req.DateChooseType),
			Weekdays:                req.Weekdays,
			Monthdays:               req.Monthdays,
			UseScenes:               req.UseScenes,
			Scope:                   req.Scope,
			ParentID:                sqlc.NInt64FromInt64(req.ParentId),
			CopySource:              sqlc.NInt64FromInt64(req.CopySource),
		},
	}

	if req.NeedVerifyQualification {
		ptr.CreatePromotionParamsPtr.QualifyTypes = req.QualifyTypes
	}
	itemCategoryConfPtrs = sharedConv.ConvItemCategoryConfigurationPtrArrayPbToEntity(req.ItemCategoryConfs)
	itemConfPtrs = sharedConv.ConvItemConfigurationPtrArrayPbToEntity(req.ItemConfs)

	slog.Infof("promotion_imp/cmd_vld.VldCreatePromotionReq ok")
	return
}

// VldUpdatePromotionReq 验证更新促销活动请求
func (s *PromotionWebApiImp) VldUpdatePromotionReq(ctx context.Context, q *sqlc.Queries, req *promotionGrpc.UpdatePromotionReq) (
	ptr *promotion.UpdatePromotionParam,
	itemCategoryConfPtrs param.ItemCategoryConfigurationPtrArray,
	itemConfPtrs param.ItemConfigurationPtrArray,
	err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	if req.Id < 0 {
		err = render.InvalidArgumentRange("id")
		return
	}
	if util.IsEmpty(req.Name) {
		err = render.ArgumentEmpty("name")
		return
	}
	if !sharedVld.IsOfferCategory(req.OfferCategory) {
		err = render.InvalidArgumentValue("offer_category")
		return
	}
	if !sharedVld.IsOfferType(req.OfferType) {
		err = render.InvalidArgumentValue("offer_type")
		return
	}
	if !sharedVld.IsIssuer(req.Issuer) {
		err = render.InvalidArgumentValue("issuer")
		return
	}
	if req.NeedVerifyQualification {
		if !sharedVld.IsQualifyTypeArray(req.QualifyTypes, false) {
			err = render.InvalidArgumentValue("qualify_types")
			return
		}
	}
	if req.Price < 0 {
		err = render.InvalidArgumentRange("price")
		return
	}
	if req.Quota < 0 {
		err = render.InvalidArgumentRange("quota")
		return
	}
	if req.OffMaximum < 0 {
		err = render.InvalidArgumentRange("off_maximum")
		return
	}
	var offMaximum int32 = -1
	switch sqlc.EmOfferType(req.OfferType) {
	case sqlc.EmOfferTypeDiscount:
		if req.Price > 100 {
			err = render.InvalidArgumentRange("price[0,100]")
			return
		}
		if req.OffMaximum <= req.Quota {
			err = render.InvalidArgumentRange("off_maximum<=quota")
			return
		}
		if req.OffMaximum > 0 {
			offMaximum = req.OffMaximum
		}
	}
	if !util.IsEmpty(req.DateChooseType) && !sharedVld.IsChooseType(req.DateChooseType) {
		err = render.InvalidArgumentValue("date_choose_type")
		return
	}
	if !sharedVld.IsOfferUseSceneArray(req.UseScenes, false) {
		err = render.InvalidArgumentValue("use_scenes")
		return
	}
	if !sharedVld.IsScope(req.Scope) {
		err = render.InvalidArgumentValue("scope")
		return
	}

	ptr = &promotion.UpdatePromotionParam{
		PromotionID:             req.Id,
		Name:                    req.Name,
		Desc:                    req.Desc,
		Tags:                    req.Tags,
		OfferCategory:           req.OfferCategory,
		OfferType:               req.OfferType,
		Issuer:                  req.Issuer,
		NeedVerifyQualification: req.NeedVerifyQualification,
		Price:                   req.Price,
		Quota:                   req.Quota,
		OffMaximum:              offMaximum,
		GradientRules:           sharedConv.ConvOffGradientRuleArrayPbToEntity(req.GradientRules),
		Begined:                 sqlc.PBTimestampToGoTime(req.Begined),
		Ended:                   sqlc.PBTimestampToGoTime(req.Ended),
		TimeRanges:              sharedConv.ConvTimeRangeArrayPbToEntity(req.TimeRanges),
		DateChooseType:          req.DateChooseType,
		Weekdays:                req.Weekdays,
		Monthdays:               req.Monthdays,
		UseScenes:               req.UseScenes,
		Scope:                   req.Scope,
	}

	if req.NeedVerifyQualification {
		ptr.QualifyTypes = req.QualifyTypes
	}

	itemCategoryConfPtrs = sharedConv.ConvItemCategoryConfigurationPtrArrayPbToEntity(req.ItemCategoryConfs)
	itemConfPtrs = sharedConv.ConvItemConfigurationPtrArrayPbToEntity(req.ItemConfs)

	slog.Infof("promotion_imp/cmd_vld.VldUpdatePromotionReq ok")
	return
}

// VldPublishPromotionReq 验证发布促销活动请求
func (s *PromotionWebApiImp) VldPublishPromotionReq(ctx context.Context, q *sqlc.Queries, req *promotionGrpc.PublishPromotionReq) (ptr *promotion.UpdatePromotionStatusParam, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	if req.Id < 0 {
		err = render.InvalidArgumentRange("id")
		return
	}
	ptr = &promotion.UpdatePromotionStatusParam{
		PromotionID: req.Id,
	}
	slog.Infof("promotion_imp/cmd_vld.VldPublishPromotionReq ok")
	return
}

// VldPausePromotionReq 验证暂停促销活动请求
func (s *PromotionWebApiImp) VldPausePromotionReq(ctx context.Context, q *sqlc.Queries, req *promotionGrpc.PausePromotionReq) (ptr *promotion.UpdatePromotionStatusParam, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	if req.Id < 0 {
		err = render.InvalidArgumentRange("id")
		return
	}
	ptr = &promotion.UpdatePromotionStatusParam{
		PromotionID: req.Id,
	}
	slog.Infof("promotion_imp/cmd_vld.VldPausePromotionReq ok")
	return
}

// VldPausePromotionReq 验证恢复促销活动请求
func (s *PromotionWebApiImp) VldResumePromotionReq(ctx context.Context, q *sqlc.Queries, req *promotionGrpc.ResumePromotionReq) (ptr *promotion.UpdatePromotionStatusParam, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	if req.Id < 0 {
		err = render.InvalidArgumentRange("id")
		return
	}
	ptr = &promotion.UpdatePromotionStatusParam{
		PromotionID: req.Id,
	}
	slog.Infof("promotion_imp/cmd_vld.VldResumePromotionReq ok")
	return
}
